package cz.muni.fi.pa165.business.daoimpl;

import cz.muni.fi.pa165.business.dao.ForestVisitDAO;
import cz.muni.fi.pa165.business.entity.Forest;
import cz.muni.fi.pa165.business.entity.ForestVisit;
import cz.muni.fi.pa165.business.entity.Picker;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.stereotype.Repository;

/**
 *
 * @author Michal Becak
 */
@Repository
public class ForestVisitDAOImpl implements ForestVisitDAO {

    @PersistenceContext
    private EntityManager em;

    @Override
    public void createVisit(ForestVisit forestVisit) {
        validateForestVisit(forestVisit, false);
        try {
            em.persist(forestVisit);
        } finally {
            em.close();
        }
    }

    @Override
    public ForestVisit getVisit(Long id) {
        if (id == null) {
            throw new IllegalArgumentException("ID is null");
        }
        if (id < 0) {
            throw new IllegalArgumentException("ID is negative");
        }
        try {
            return em.find(ForestVisit.class, id);
        } finally {
            em.close();
        }
    }

    @Override
    public void removeVisit(ForestVisit forestVisit) {
        validateForestVisit(forestVisit, true);
        try {
            ForestVisit f = em.find(ForestVisit.class, forestVisit.getId());
            em.remove(f);
        } finally {
            em.close();
        }
    }

    @Override
    public void updateVisit(ForestVisit forestVisit) {
        validateForestVisit(forestVisit, true);
        try {
            ForestVisit fv = em.find(ForestVisit.class, forestVisit.getId());
            fv.setDateOfVisit(forestVisit.getDateOfVisit());
            fv.setDescription(forestVisit.getDescription());
            fv.setForest(forestVisit.getForest());
            fv.setPicker(forestVisit.getPicker());
            fv.setMushroomsFound(forestVisit.getMushroomsFound());
        } finally {
            em.close();
        }
    }

    @Override
    public List<ForestVisit> retrieveAllVisits() {
        try {
            Query queryFindAll = em.createQuery("SELECT fv from "
                    + "cz.muni.fi.pa165.business.entity.ForestVisit fv");
            return queryFindAll.getResultList();
        } finally {
            em.close();
        }
    }

    @Override
    public List<ForestVisit> retrieveVisitsByPicker(Picker picker) {
        if (picker == null) {
            throw new IllegalArgumentException("picker is null");
        }
        try {
            Query queryFindAll = em.createQuery("SELECT fv from "
                    + "cz.muni.fi.pa165.business.entity.ForestVisit fv where fv.picker = :idPicker")
                    .setParameter("idPicker", picker);
            return queryFindAll.getResultList();
        } finally {
            em.close();
        }
    }

    @Override
    public List<ForestVisit> retrieveVisitsByForest(Forest forest) {
        if (forest == null) {
            throw new IllegalArgumentException("forest is null");
        }
        try {
            Query queryFindAll = em.createQuery("SELECT fv from "
                    + "cz.muni.fi.pa165.business.entity.ForestVisit fv where fv.forest = :idForest")
                    .setParameter("idForest", forest);
            return queryFindAll.getResultList();
        } finally {
            em.close();
        }
    }

    private void checkForestsEquality(Forest forest1, Forest forest2) {
        if (forest1 == null || forest2 == null) {
            throw new IllegalArgumentException("Given forest is null or not in DB");
        }
        if (!(stringEqualsNullable(forest1.getName(), forest2.getName())
                && stringEqualsNullable(forest1.getLocationInfo(), forest2.getLocationInfo()))) {
            throw new IllegalArgumentException("Given forest is not the same as in DB");
        }
    }

    private void checkPickersEquality(Picker picker1, Picker picker2) {
        if (picker1 == null || picker2 == null) {
            throw new IllegalArgumentException("Given picker is null or not in DB");
        }
        if (!(stringEqualsNullable(picker1.getNickName(), picker2.getNickName())
                && stringEqualsNullable(picker1.getFirstName(), picker2.getFirstName())
                && stringEqualsNullable(picker1.getLastName(), picker2.getLastName())
                && stringEqualsNullable(picker1.getPickerInfo(), picker2.getPickerInfo()))) {
            throw new IllegalArgumentException("Given picker is not the same as in DB");
        }
    }

    private boolean stringEqualsNullable(String str1, String str2) {
        if (str1 != null) {
            if (str1.equals(str2)) {
                return true;
            }
        } else {
            if (str2 == null) {
                return true;
            }
        }
        return false;
    }

    private void validateForestVisit(ForestVisit forestVisit, boolean isInDB) {
        if (forestVisit == null) {
            throw new IllegalArgumentException("forestVisit is null");
        }
        if (forestVisit.getPicker() == null) {
            throw new IllegalArgumentException("picker is null");
        }
        if (forestVisit.getPicker().getId() == null) {
            throw new IllegalArgumentException("picker id is null");
        }
        if (forestVisit.getForest() == null) {
            throw new IllegalArgumentException("forest is null");
        }
        if (forestVisit.getForest().getId() == null) {
            throw new IllegalArgumentException("forest id is null");
        }
        if (forestVisit.getDateOfVisit() == null) {
            throw new IllegalArgumentException("dateOfVisit is null");
        }
        if (forestVisit.getDescription() == null) {
            throw new IllegalArgumentException("description is null");
        }
        if (forestVisit.getMushroomsFound() == null) {
            throw new IllegalArgumentException("mushrooms found list is null");
        }
//        if (!isInDB) {
//            if (forestVisit.getId() != null) {
//                throw new IllegalArgumentException("forestVisit is already in DB");
//            }
//        } else {
//            if (forestVisit.getId() == null) {
//                throw new IllegalArgumentException("forestVisit is already in DB");
//            }
//        }
        //ForestDAOImpl forestDAO; = new ForestDAOImpl();
        //PickerDAOImpl pickerDAO = new PickerDAOImpl();
//        forestDAO.setEmf(emf);
//        pickerDAO.setEmf(emf);
        //Forest forest = forestDAO.getForest(forestVisit.getForest().getId());
        //Picker picker = pickerDAO.getPicker(forestVisit.getPicker().getId());
        //checkForestsEquality(forestVisit.getForest(), forest);
        //checkPickersEquality(forestVisit.getPicker(), picker);
    }
}
